//
// @Auther: by wujehy 
// @Email:wujehy@qq.com
// @Data:2019/10/08
// @Time:11:09 上午
//
//

#ifndef  MQTT_PLUGIN_LOGGER_H
#define  MQTT_PLUGIN_LOGGER_H


#include <sstream>
#include <vector>

class Logger
{
public:
    enum LogType
    {
        Debug,
        Info,
        Warning,
        Error,
        Default,
    };

    struct Stream
    {
        Stream() : ss()
        {}

        Stream(std::string *s) : ss( *s )
        {}
        std::string funcName ;
        std::string fileName ;
        int lineNub ;
        std::ostringstream ss;
        LogType logType;
    } *stream;

    inline Logger &operator<<(bool t)
    {
        stream->ss << (t ? "true" : "false");
        return *this;
    }

    inline Logger &operator<<(char t)
    {
        stream->ss << t;
        return *this;
    }

    inline Logger &operator<<(signed short t)
    {
        stream->ss << t;
        return *this;
    }

    inline Logger &operator<<(int t)
    {
        stream->ss << t;
        return *this;
    }

    inline Logger &operator<<(int64_t t)
    {
        stream->ss << t;
        return *this;
    }

    inline Logger &operator<<(unsigned short t)
    {
        stream->ss << t;
        return *this;
    }

    inline Logger &operator<<(std::string s)
    {
        stream->ss << s;
        return *this;
    }

    inline Logger &operator<<(const char *c)
    {
        stream->ss << c;
        return *this;
    }


    template<typename T>
    inline Logger &operator<<(const std::vector<T> &vec)
    {
        stream->ss << '(';
        for (int i = 0; i < vec.size(); ++i)
        {
            stream->ss << vec.at( i );
            stream->ss << ", ";
        }
        stream->ss << ')';
        return *this;
    }

    Logger(LogType type ,const char *file ,  const char *func , int line) : stream( new Stream())
    {
        stream->logType = type;
        stream->funcName = func;
        stream->fileName = file;
        stream->lineNub = line;
    }

    inline Logger(std::string *s) : stream( new Stream( s ))
    {}

    virtual ~Logger();

    void LogToConsole(LogType, const std::string &);

private:
    static Logger *_instance;
};


#define gDebug Logger(Logger::Debug ,__FILE__,__FUNCTION__ ,__LINE__)
#define gInfo Logger(Logger::Info,__FILE__,__FUNCTION__ ,__LINE__)
#define gWarning Logger(Logger::Warning,__FILE__,__FUNCTION__ ,__LINE__)
#define gError Logger(Logger::Error,__FILE__,__FUNCTION__ ,__LINE__)
#endif // MQTT_PLUGIN_LOGGER_H
